package com.ys.service.purchase.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.AddDto;
import com.ys.entity.base.CheckByGrid;
import com.ys.entity.flow.YspModel;
import com.ys.entity.purchase.TcgPurchaseContractItem;
import com.ys.entity.purchase.TcgPurchaseInStorage;
import com.ys.entity.purchase.TcgPurchasePreStorage;
import com.ys.entity.purchase.TcgPurchasePreStorageSon;
import com.ys.entity.sys.TsUserChange;
import com.ys.entity.sys.YsCol;
import com.ys.entity.sys.YsGridCol;
import com.ys.entity.sys.YsMenu;
import com.ys.entity.sys.YsProcInst;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.product.ProductMapper;
import com.ys.mapper.purchase.TcgPurchaseContractItemMapper;
import com.ys.mapper.purchase.TcgPurchaseInStorageMapper;
import com.ys.mapper.purchase.TcgPurchasePreStorageMapper;
import com.ys.mapper.purchase.TcgPurchasePreStorageSonMapper;
import com.ys.service.flow.YspTaskService;
import com.ys.service.purchase.TcgPurchasePreStorageService;
import com.ys.service.sys.CommonApiService;
import com.ys.util.CheckUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;

/**
 *
 */
@Service("tcgPurchasePreStorageService")
public class TcgPurchasePreStorageServiceImpl implements TcgPurchasePreStorageService {
    private static final Logger logger = LoggerFactory.getLogger(TcgPurchasePreStorageServiceImpl.class);

    @Autowired
    private CheckUtil checkUtil;

    private final Long GRID = 49L;

    @Autowired
    private TcgPurchasePreStorageMapper tcgPurchasePreStorageMapper;

    @Autowired
    private YspTaskService yspTaskService;

    @Autowired
    private TcgPurchasePreStorageSonMapper tcgPurchasePreStorageSonMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private CommonApiService<TcgPurchaseInStorage> commonApiService;

    @Autowired
    private TcgPurchaseInStorageMapper tcgPurchaseInStorageMapper;

    @Autowired
    private TcgPurchaseContractItemMapper tcgPurchaseContractItemMapper;


    /**
     * 新增
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R add(Map<String, Object> params, Long menuId) throws Exception{
        logger.info("新增传参:"+params);
        //参数验证
        String errorBack = checkParams(params, menuId);
        if(errorBack!=null && !"".equals(errorBack)){
            return R.error(errorBack);
        }
        TcgPurchasePreStorage entity = JSON.parseObject(JSON.toJSONString(params), TcgPurchasePreStorage.class);
        entity.setStatus(1);//状态
        entity.setEffectStock(0);//审批状态

        //获取制单人信息
        TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setStatus(1).queryFirst();
        if(tsUserChange!=null){
            entity.setCreateChangeId(tsUserChange.getId());//制单人变更信息
        }else {
            return R.error("未查询到制单人信息！");
        }

        //保存列表信息
        R saveItemRes = saveItem(params,entity);
        if(saveItemRes.getCode()==1){
            throw new RuntimeException(saveItemRes.getMsg());
        }

        //新增
        tcgPurchasePreStorageMapper.insert(entity);

        YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
        if (ysMenu.getFlowModelId().longValue() != 0L) {
            YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
            String codeModel = yspModel.getCode();
            String createUserId = ShiroUtils.getUserId();
            yspTaskService.init(codeModel, entity.getBid(), createUserId);
        }
        return R.ok(AddDto.gotoEdit("/web/purchase/tcgPurchasePreStorage/toEdit?bid=" + entity.getBid()));
    }

    /**
     * 修改
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R update(Map<String, Object> params, Long menuId) throws Exception{
        logger.info("修改传参:"+params);
        //参数验证
        String errorBack = checkParams(params, menuId);
        if(errorBack!=null && !"".equals(errorBack)){
            return R.error(errorBack);
        }
        TcgPurchasePreStorage entity = JSON.parseObject(JSON.toJSONString(params), TcgPurchasePreStorage.class);
        // 验证状态
        YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
        if (ysProcInst == null) {
            return R.error("审批数据不存在，无法编辑");
        } else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.INIT.value) {
            return R.error("已流转，无法编辑");
        }

        //保存列表信息
        R saveItemRes = saveItem(params,entity);
        if(saveItemRes.getCode()==1){
            throw new RuntimeException(saveItemRes.getMsg());
        }
        tcgPurchasePreStorageMapper.update(entity);
        return R.ok(AddDto.gotoEdit("/web/purchase/tcgPurchasePreStorage/toEdit?bid=" + entity.getBid()));

    }

    //删除
    @Override
    @Transactional
    public R del(Long id) throws Exception{
        if (id == null) {
            return R.error("ID不能为空");
        }
        TcgPurchasePreStorage entity = new TcgPurchasePreStorage().setId(id).queryFirst();
        if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
            return R.error("已生效数据无法删除");
        }
        // 验证是否制单人
        String loginUserId = ShiroUtils.getUserId();
        TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
        if (!tsUserChange.getUserId().equals(loginUserId) && !"admin".equals(loginUserId)) {
            return R.error("非制单人，无法删除");
        }
        //删除
        tcgPurchasePreStorageMapper.deleteTrue(id);
        //删除列表信息
        productMapper.deleteTcgPurchasePreStorageSonByPbid(entity.getBid());
        //删除流程
        yspTaskService.flowDelete(entity.getBid(), loginUserId);
        return R.ok();
    }

    /**
     * 流转通过
     */
    @Override
    @Transactional
    public R flowPass(String bid,String userId) throws Exception {
        //获取单据信息
        TcgPurchasePreStorage entity = new TcgPurchasePreStorage().setBid(bid).queryFirst();
        if (entity == null) {
            return R.error("该单据不存在,请核实后再操作!");
        }


        if(new TcgPurchasePreStorageSon().setPbid(bid).count() == 0){
            return R.error("该单据列表不存在,请核实后再操作!");
        }

        try {
            Flow f = yspTaskService.flowPass(bid, userId);
            if (f.getCode() == Flow.Code.FAILED.value) {
                return R.error(f.getMsg());
            } else {
                if (f.getState() == Flow.State.FINISH.value) {
                    R r = flowFinish(entity);
                    if (r.getCode() == 1) {
                        return R.error(r.getMsg());
                    }
                }
                return R.ok();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 流转结束
     */
    @Transactional
    public R flowFinish(TcgPurchasePreStorage entity) throws Exception {
        entity.setEffectStock(1);
        tcgPurchasePreStorageMapper.update(entity);

        List<Map<String, Object>> sonlist = new TcgPurchasePreStorageSon()
                .setPbid(entity.getBid())
                .addLeftJoin("TCG_PurchaseContractItem tpc on tpc.id = A.PurchaseContractItemId")//采购合同管理（采购合同单明细）
                .addLeftJoin("TCG_PurchaseContract tpcct on tpcct.bid = tpc.Pbid")//采购合同单
                .addField("tpcct.partnerBankInfoId")
                .addField("tpc.Pbid purchaseContractBid,tpc.SubPurchasePrice subPurchasePrice,tpc.id purchaseContractItemId,tpc.subBomNumber subBomNumber")
                .addLeftJoin("TCG_PurchaseAppointOrderProductComponent paoc on paoc.id = tpc.OrderProductComponentId")//预约采购子件明细
                .addField("paoc.SubCode subCode,paoc.subName subName,paoc.subCodeMerge subCodeMerge")
                .addLeftJoin("TCG_PurchaseAppointOrderItem paoi on paoi.id = paoc.pid")//预约采购商品明细
                .addField("paoi.Pbid appointOrderBid,paoi.ProductCode productCode,paoi.ProductName productName,paoi.CodeMerge codeMerge")
                .addLeftJoin("TCG_PurchaseAppointOrder pao on pao.Bid = paoi.Pbid")//预约采购单
                .addLeftJoin("THR_OperateCompanyApply TOCA ON TOCA.Vgsbm = pao.Vgsbm")
                .addField("pao.Vgsbm vgsbm,TOCA.Vgsjc AS vgsjc")//运营公司简称
                .addField("pao.companyVid companyVid,pao.bid purchaseAppointOrderBid")
                .queryMap();

        for (Map<String, Object> son : sonlist){
            TcgPurchaseContractItem tcgPurchaseContractItem = new TcgPurchaseContractItem().setId(Long.valueOf(son.get("purchaseContractItemId").toString())).queryFirst();
            TcgPurchaseInStorage tcgPurchaseInStorage = new TcgPurchaseInStorage();
            tcgPurchaseInStorage.setBid(commonApiService.getCommonNextBid(MenuId.TCG_PurchaseInStorage));
            tcgPurchaseInStorage.setPurchasePreStorageBid(entity.getBid());
            tcgPurchaseInStorage.setPurchaseContractBid(son.get("purchaseContractBid").toString());
            tcgPurchaseInStorage.setCompanyVid(son.get("companyVid").toString());
            tcgPurchaseInStorage.setPartnerBankInfoId(son.get("partnerBankInfoId").toString());
            tcgPurchaseInStorage.setEstimatedArrivalTime(entity.getEstimatedArrivalTime());
            tcgPurchaseInStorage.setLogisticsMode(entity.getLogisticsMode());
            tcgPurchaseInStorage.setTrackingNumber(entity.getTrackingNumber());
            tcgPurchaseInStorage.setPurchaseAppointOrderBid(son.get("purchaseAppointOrderBid").toString());
            tcgPurchaseInStorage.setVgsbm(son.get("vgsbm").toString());
            tcgPurchaseInStorage.setProductCode(son.get("productCode").toString());
            tcgPurchaseInStorage.setProductName(son.get("productName").toString());
            tcgPurchaseInStorage.setCodeMerge(son.get("codeMerge").toString());
            tcgPurchaseInStorage.setSubCode(son.get("subCode").toString());
            tcgPurchaseInStorage.setSubName(son.get("subName").toString());
            tcgPurchaseInStorage.setSubCodeMerge(son.get("subCodeMerge").toString());
            tcgPurchaseInStorage.setSubBomNumber(new Integer(son.get("subBomNumber").toString()));
            tcgPurchaseInStorage.setSubPurchasePrice(new BigDecimal(son.get("subPurchasePrice").toString()));
            tcgPurchaseInStorage.setSubStorageNum(new Integer(son.get("preStorageNum").toString()));
            tcgPurchaseInStorage.setStorageStatus(0);
            tcgPurchaseInStorage.setAssembledStatus(0);
            tcgPurchaseInStorage.setDocumentSource(0);
            tcgPurchaseInStorage.setPurchasePreStorageSonId(Long.parseLong(son.get("id").toString()));
            tcgPurchaseInStorage.setPurchaseAppointOrderProductComponentId(tcgPurchaseContractItem.getOrderProductComponentId());
            tcgPurchaseInStorage.setStatus(0);
            tcgPurchaseInStorageMapper.insert(tcgPurchaseInStorage);
        }
        return R.ok();
    }

    //流转驳回
    public R flowRefuse(String bid, String reason,String userId	) throws Exception{

        R r = yspTaskService.flowRefuse(bid, reason,userId);

        return r;
    }


    //流转退回
    public R flowInit(String bid, String reason,String userId) throws Exception{
        R r = yspTaskService.flowInit(bid, reason, userId);
        if (r.getCode() == R.Code.SUCCESS.value) {
            YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
            // 若退回到制单状态，则解冻账户
            if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {

            }
        }
        return r;
    }

    /**
     * 参数验证
     */
    public String checkParams(Map<String, Object> params, Long menuId) throws Exception {
        //获取pc字段数据
        List<YsCol> listField = new YsCol()
                .where("A.MenuId = "+menuId)
                .setOrderby("A.SortNo ASC")
                .queryList();
        //验证必填字段的非空；其他字段的长度限制、类型
        String backMsg = checkUtil.checkTableColLengthAndDataType("TCG_PurchasePreStorage",listField,params,ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1);
        return backMsg;
    }

    //保存子列表信息
    public R saveItem(Map<String, Object> params, TcgPurchasePreStorage entity) throws Exception{
        //保存列表信息
        List<Map<String, Object>> subDataList = new ArrayList<>();
        if(params.get("subData")!=null){
            JSONArray subData = JSON.parseArray(params.get("subData").toString());
            CheckByGrid checkByGrid = checkParamsByGrid(subData,GRID);
            if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
                return R.error(checkByGrid.getErrMsg());
            }
            subDataList = checkByGrid.getSubDataList();
        }else {
            return R.error("列表信息为空！");
        }

        List<TcgPurchasePreStorageSon> tcgPurchasePreStorageSonList = new TcgPurchasePreStorageSon().setPbid(entity.getBid()).queryList();
        TcgPurchaseContractItem tcgPurchaseContractItem;
        for (TcgPurchasePreStorageSon tcgPurchasePreStorageSon : tcgPurchasePreStorageSonList){
            //扣减预入库数量
            tcgPurchaseContractItem = new TcgPurchaseContractItem().setId(tcgPurchasePreStorageSon.getPurchaseContractItemId()).queryFirst();
            tcgPurchaseContractItem.setSubPreWarehousingNum(tcgPurchaseContractItem.getSubPreWarehousingNum() - tcgPurchasePreStorageSon.getPreStorageNum());
            tcgPurchaseContractItemMapper.update(tcgPurchaseContractItem);
        }

        //先删除采购合同详情数据
        productMapper.deleteTcgPurchasePreStorageSonByPbid(entity.getBid());
        //再新增
        for (int i = 0; i < subDataList.size(); i++) {
            Map<String, Object> item = subDataList.get(i);
            TcgPurchasePreStorageSon itemInfo = JSON.parseObject(JSON.toJSONString(item), TcgPurchasePreStorageSon.class);
            itemInfo.setStatus(1);
            itemInfo.setPbid(entity.getBid());
            //判断是否该采购合同数据是否完整入库
            Integer count = new TcgPurchasePreStorageSon()
                    .setPurchaseContractItemId(itemInfo.getPurchaseContractItemId())
                    .addLeftJoin("TCG_PurchasePreStorage pps on pps.bid = A.pbid")
                    .where("A.pbid !='"+entity.getBid()+"' AND pps.EffectStock = 0")
                    .count();
            if (count != 0){
                return R.error("采购预入库存在相同的还未入库的数据,请核实后再操作!");
            }
            count = new TcgPurchaseContractItem()
                    .setId(itemInfo.getPurchaseContractItemId())
                    .where("(A.SubPurchaseNum - A.SubWarehousingNum) < " + itemInfo.getPreStorageNum())
                    .count();
            if (count != 0){
                return R.error("未入库数量不足,请核实后再操作!");
            }
            count = new TcgPurchaseInStorage()
                    .addLeftJoin("TCG_PurchasePreStorageSon pss on pss.id = A.PurchasePreStorageSonId")//采购预入库子件
                    .where("pss.PurchaseContractItemId ='"+itemInfo.getPurchaseContractItemId()+"' AND A.StorageStatus = 0")
                    .count();
            if (count != 0){
                return R.error("采购入库存在相同的还未入库的数据,请核实后再操作!");
            }

            //新增
            tcgPurchasePreStorageSonMapper.insert(itemInfo);

            //增加预入库数量
            tcgPurchaseContractItem = new TcgPurchaseContractItem().setId(itemInfo.getPurchaseContractItemId()).queryFirst();
            tcgPurchaseContractItem.setSubPreWarehousingNum(tcgPurchaseContractItem.getSubPreWarehousingNum() + itemInfo.getPreStorageNum());
            tcgPurchaseContractItemMapper.update(tcgPurchaseContractItem);
        }
        return R.ok();
    }

    /**
     * 子表参数验证
     */
    public CheckByGrid checkParamsByGrid(JSONArray subDataArray, Long gridId) throws Exception {
        CheckByGrid checkByGrid = new CheckByGrid();
        //获取pc字段数据
        List<YsGridCol> listField = new YsGridCol()
                .setGridId(gridId)
                .setOrderby("A.SortNo ASC")
                .queryList();
        String backMsg = "";
        List<Map<String, Object>> subDataList = new ArrayList<>();

        if(subDataArray!=null && subDataArray.size()>0){
            for (int i = 0; i < subDataArray.size(); i++) {
                JSONObject jsonObject = subDataArray.getJSONObject(i);
                Map<String, Object> paramsNewByRecord = new HashMap<>();
                for (String key : jsonObject.keySet()) {
                    paramsNewByRecord.put(key, jsonObject.get(key));
                }
                subDataList.add(paramsNewByRecord);
            }
            //验证
            for(int i = 0;i<subDataList.size();i++){
                String backMsgByRow = "";
                Map<String, Object> subData = subDataList.get(i);
                //验证必填字段的非空；其他字段的长度限制、类型
                backMsgByRow += checkUtil.checkTableColLengthAndDataTypeByGrid(
                        "TCG_PurchasePreStorageSon",
                        listField,
                        subData,
                        ysColItem->
                                ysColItem.getCode().equals("appointOrderId")
                                        || ysColItem.getCode().equals("subPurchaseNum")
                                        || ysColItem.getCode().equals("subPurchasePrice")
                                        || ysColItem.getCode().equals("purchaseTotalPrice")
                                        || ysColItem.getCode().equals("subBomNumber")
                );
                if(checkUtil.isNotNullByObject(backMsgByRow)){
                    backMsg += "列表第" + (i+1) + "行，" + backMsgByRow;
                }
            }
        }else{
            backMsg = "列表信息为空";
        }
        checkByGrid.setErrMsg(backMsg);
        checkByGrid.setSubDataList(subDataList);

        return checkByGrid;
    }


    //获取列表数据
    @Override
    @Transactional
    public Map<String,Object> getExtraParam( String bid) throws Exception{
        Map entity = new TcgPurchasePreStorage().setBid(bid)
                .addLeftJoin("YS_ProcInst Ysp ON Ysp.bid = A.bid")//流程表
                .addField("FORMAT(Ysp.UpdateTime, 'yyyy-MM-dd hh:mm:ss') AS updateTime1")//审核时间
                .addField("FORMAT(A.createTime, 'yyyy-MM-dd hh:mm:ss') AS createTime1")//创建时间
                .addLeftJoin("TCG_PurchaseContract pc on pc.bid = A.PurchaseContractBid")//采购合同单
                .addLeftJoin("TCW_PartnerBankInfo C on C.id = pc.PartnerBankInfoId")//供应方公司
                .addField("C.PartnerName partnerBankInfoName")
                .addLeftJoin("TB_CompanyInfo D ON D.Vid = pc.CompanyInfoVid")//购买方公司
                .addField("D.Vname companyName")
                .queryFirstMap();
        return entity;
    }
    //获取子列表数据
    @Override
    @Transactional
    public List<Map<String, Object>> getItemList( String bid) throws Exception{
        List<Map<String, Object>> sonlist = new TcgPurchasePreStorageSon()
                .setPbid(bid)
                .addLeftJoin("TCG_PurchaseContractItem tpc on tpc.id = A.PurchaseContractItemId")//采购合同管理（采购合同单明细）
                .addField("tpc.Pbid purchaseContractBid,tpc.SubPurchasePrice subPurchasePrice,tpc.id purchaseContractItemId,tpc.subBomNumber subBomNumber")
                .addLeftJoin("TCG_PurchaseAppointOrderProductComponent paoc on paoc.id = tpc.OrderProductComponentId")//预约采购子件明细
                .addField("paoc.SubCode subCode,paoc.subName subName,paoc.subCodeMerge subCodeMerge")
                .addLeftJoin("TCG_PurchaseAppointOrderItem paoi on paoi.id = paoc.pid")//预约采购商品明细
                .addField("paoi.Pbid appointOrderBid,paoi.ProductCode productCode,paoi.ProductName productName,paoi.CodeMerge codeMerge")
                .addLeftJoin("TCG_PurchaseAppointOrder pao on pao.Bid = paoi.Pbid")//预约采购单
                .addLeftJoin("THR_OperateCompanyApply TOCA ON TOCA.Vgsbm = pao.Vgsbm")
                .addField("pao.Vgsbm vgsbm,TOCA.Vgsjc AS vgsjc")//运营公司简称
                .queryMap();
        return sonlist;
    }



}
